-module(session_service).
-include("rec_dec.hrl").
-behaviour(gen_server).
-export([start/0,init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3,getLoginRec/1,getLoginedInfo/2,addHistory/2]).
start() ->
	case gen_server:start({local, ?MODULE}, ?MODULE, [], []) of 
	{ok,_} ->
		timer:send_interval(60000,session_service,timeout),
		ok;
	{error,Reason} ->
		io:format("start session service failure with ~p~n",[Reason])
	end.
init(_) ->
	error_logger:info_msg("session service is started~n"),
    {ok,[]}.
handle_call({logout,Session_Id},_,Users) ->
	case lists:keyfind(Session_Id,1,Users) of
		false ->
			{reply,ok,Users};
		{Session_Id,LoginRec} ->
			user_service:addchange(LoginRec#login_rec{logout_date = calendar:local_time()}),
			{reply,ok,lists:keydelete(Session_Id,1,Users)}
		end;
handle_call({login,LoginRec},_,Users) ->
	NewUsers = force_logout(LoginRec#login_rec.user_id,Users),
	Id = gen_server:call(couch_uuids,create),
	[U|_] = user_service:get({id,LoginRec#login_rec.user_id}),
	case U#user_rec.state of
	first_login ->
		user_service:addchange(U#user_rec{state = normal});
	_ ->
		ok
	end,
	io:format("login session created ~p~n",[LoginRec]),
	{reply,{ok,Id},[{Id,LoginRec#login_rec{id=Id}}|NewUsers]};
handle_call(timeout,_,Users) ->
	io:format("timeout message received~n"),
	{reply,ok,Users};
	
handle_call({update,L_Id,{Field,Value}},_,Users) ->
	UpdateF = fun(U) ->
			case Field of
			vendor_id ->
				U#login_rec{vendor_id = Value};
			vendor_name ->
				U#login_rec{vendor_name = Value};
			history ->
				{Key,_,_} = Value,
				U#login_rec{history = [Value | lists:keydelete(Key,1,U#login_rec.history)]};
			_ ->
				U
			end
	end,
	io:format("update history with ~p,~p,~p~n",[L_Id,Field,Value]),
	{reply,ok,lists:map(
				fun({Id,U}) ->
					case Id of
					L_Id ->
						{Id,UpdateF(U)};
					_ ->
						{Id,U}
					end
				end,
				Users)
	};

handle_call({retrieve,Id},_,Users) ->
	{reply,
		case lists:keyfind(Id,1,Users) of
		false ->
			false;
		{Id,LoginRec} ->
			{Id,LoginRec}
		end,
	Users};
handle_call({search,LoginName},_,Users) ->
	{reply,
	lists:filter(fun({_,U}) ->
					U#login_rec.login_name =:= LoginName
				end,
				Users
			),
	Users
	};
handle_call(dump,_,Users) ->
	{reply,Users,Users};
handle_call(stop,_,Users) ->
	{stop,Users,Users};
handle_call(Cmd,Param,State) ->
	io:format("undefine Cmd:~p with param:~p~n",[Cmd,Param]),
	{reply, undefined, State}.	
handle_cast(_, State) ->
	{noreply,State}.
handle_info(_, State) ->
	{noreply,State}.
terminate(_, _) ->
	ok.
code_change(_, State, _) ->
	{ok,State}.
getLoginRec(Id) ->
	case gen_server:call(session_service,{retrieve,Id}) of
	{Id,LoginRec} ->
		LoginRec;
	_ ->
		#login_rec{
			user_id = "unknown",
			mode = unauth,
			vendor_id = "unknown",
			vendor_name = "unknown",
			login_name = "unknown"
		}
	end.
getLoginedInfo(L,vendor_id) ->
	(session_service:getLoginRec(
											tools:get_param(L,"_inter_session_id","undefined")
											)
	)#login_rec.vendor_id;
getLoginedInfo(L,mode) ->
	(session_service:getLoginRec(
											tools:get_param(L,"_inter_session_id","undefined")
											)
	)#login_rec.mode;
getLoginedInfo(L,register_id) ->
	(session_service:getLoginRec(
											tools:get_param(L,"_inter_session_id","undefined")
											)
	)#login_rec.register_id;

getLoginedInfo(L,user_id) ->
	(session_service:getLoginRec(
											tools:get_param(L,"_inter_session_id","undefined")
											)
	)#login_rec.user_id;

getLoginedInfo(L,state) ->
	(session_service:getLoginRec(
											tools:get_param(L,"_inter_session_id","undefined")
											)
	)#login_rec.state;
	
getLoginedInfo(L,history) ->
	(session_service:getLoginRec(
											tools:get_param(L,"_inter_session_id","undefined")
											)
	)#login_rec.history;
	
getLoginedInfo(login_info,E) when is_record(E,vendor_rec) ->
	gen_server:call(session_service,{retrieve_by_vendor,E#vendor_rec.id}).

addHistory(L,{Tag,Title,{abs_path,Href}}) ->
	NewHref = tools:replace(Href,"success","clear"),
	gen_server:call(session_service,{update,tools:get_param(L,"_inter_session_id",<<"undefined">>),{history,{Tag,Title,{abs_path,NewHref}}}}).
force_logout(UserId,Users) ->
	force_logout_A(UserId,Users,[]).
force_logout_A(_,[],NewUsers) ->
	NewUsers;
	
force_logout_A(UserId,[{_,Old_Log}|Others],NewUsers) when Old_Log#login_rec.user_id == UserId->
	user_service:addchange(Old_Log#login_rec{logout_date = calendar:local_time()}),
	force_logout_A(UserId,Others,NewUsers);
	
force_logout_A(UserId,[U|Others],NewUsers) ->
	force_logout_A(UserId,Others,[U|NewUsers]).